/*******************************************************************************
 * Copyright 2010 MoBrite (A venture of Kinara Systems Private Limited)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.mobrite.domaindroid.util;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringBufferInputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Properties;

import com.mobrite.domaindroid.Constants;
import com.mobrite.domaindroid.DomainDroidException;
import com.mobrite.domaindroid.whoisparser.DefaultWhoisResponseParser;
import com.mobrite.domaindroid.whoisparser.WhoisResponseParser;

public class WhoisUtil {

	public static final Properties WHOIS_SERVERS = createWhoisServerMap();
	private static final HashMap<String, WhoisResponseParser> WHOIS_RESPONSE_PARSER_MAP = createResponseParserMap();

	public static boolean checkAvailability (String domain, String tld) throws DomainDroidException {
		
		String response = getWhoisData(WhoisUtil.WHOIS_SERVERS.getProperty(tld), domain);		
		WhoisResponseParser parser = WhoisUtil.getWhoisResponseParserForTld(tld);
		return parser.isAvailable(response, domain);
		
	}
	
	public static String getWhoisData (String server, String domain) throws DomainDroidException {
		
	    try {
			Socket theSocket = new Socket(server, Constants.DEFAULT_WHOIS_PORT);
			Writer out
			 = new OutputStreamWriter(theSocket.getOutputStream(), "ASCII");
			BufferedReader in = new BufferedReader(new
			 InputStreamReader(theSocket.getInputStream(), "ASCII"));
			out.write(domain + "\r\n");
			out.flush();
			StringBuffer response = new StringBuffer();
			String theLine = null;
			while ((theLine = in.readLine()) != null) {
			  response.append(theLine);
			  response.append("\r\n");
			}
			theSocket.close();

			return response.toString();
		} catch (UnknownHostException e) {
			e.printStackTrace();
			throw new DomainDroidException();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			throw new DomainDroidException();
		} catch (IOException e) {
			e.printStackTrace();
			throw new DomainDroidException();
		}

	}

	private static Properties createWhoisServerMap() {

		String tldServersStr = 
			"edu=whois.educause.net\n"
			+"gov=whois.nic.gov\n"
			+"int=whois.iana.org\n"
			+"arpa=whois.iana.org\n"
			+"aero=whois.aero\n"
			+"asia=whois.nic.asia\n"
			+"biz=whois.nic.biz\n"
			+"cat=whois.cat\n"
			+"coop=whois.nic.coop\n"
			+"info=whois.afilias.info\n"
			+"mobi=whois.dotmobiregistry.net\n"
			+"museum=whois.museum\n"
			+"name=whois.nic.name\n"
			+"pro=whois.registrypro.pro\n"
			+"tel=whois.nic.tel\n"
			// TODO: Following TLD's are pending analysis
			+"travel=whois.nic.travel\n"
			+"ac=whois.nic.ac\n"
			+"ae=whois.aeda.net.ae\n"
			+"af=whois.nic.af\n"
			+"ag=whois.nic.ag\n"
			+"ai=whois.ai\n"
//			+"am=whois.nic.am\n"
			+"as=whois.nic.as\n"
			+"at=whois.nic.at\n"
			+"au=whois.ausregistry.net.au\n"
			+"be=whois.dns.be\n"
//			+"bg=whois.register.bg\n"
//			+"bj=whois.nic.bj\n"
//			+"bo=whois.nic.bo\n"
			+"br=whois.nic.br\n"
//			+"ca=whois.cira.ca\n"
			+"cc whois.nic.cc\n"
//			+"cd=whois.nic.cd\n"
//			+"ch=whois.nic.ch\n"
//			+"ci=www.nic.ci\n"
//			+"ck=whois.nic.ck\n"
//			+"cl=whois.nic.cl\n"
//			+"cm=whois.netcom.cm\n"
//			+"edu.cn=whois.edu.cn\n"
//			+"cn=whois.cnnic.cn\n"
//			+"uk.co=whois.uk.co\n"
//			+"cx=whois.nic.cx\n"
//			+"cz=whois.nic.cz\n"
			+"de=whois.denic.de\n"
//			+"dk=whois.dk-hostmaster.dk\n"
//			+"dm=whois.nic.dm\n"
//			+"dz=whois.nic.dz\n"
//			+"ee=whois.eenet.ee\n"
			+"eu=whois.eu\n"
//			+"fi=whois.ficora.fi\n"
//			+"fj=whois.usp.ac.fj\n"
//			+"fo=whois.ripe.net\n"
//			+"fr=whois.nic.fr\n"
//			+"gd=whois.adamsnames.tc\n"
//			+"gg=whois.gg\n"
//			+"gl=whois.nic.gl\n"
//			+"gm=whois.ripe.net\n"
//			+"gp=whois.nic.gp\n"
//			+"gs=whois.nic.gs\n"
//			+"gy=whois.registry.gy\n"
//			+"hk=whois.hkirc.hk\n"
//			+"hm=whois.registry.hm\n"
//			+"ht=whois.nic.ht\n"
//			+"hu=whois.nic.hu\n"
//			+"id=whois.pandi.or.id\n"
//			+"ie=whois.domainregistry.ie\n"
//			+"il=whois.isoc.org.il\n"
//			+"im=whois.nic.im\n"
			+"in=whois.registry.in\n"
//			+"io=whois.nic.io\n"
//			+"ir=whois.nic.ir\n"
//			+"is=whois.isnic.is\n"
//			+"it=whois.nic.it\n"
//			+"je=whois.je\n"
//			+"jp=whois.jprs.jp\n"
//			+"ke=whois.kenic.or.ke\n"
//			+"kg=whois.domain.kg\n"
//			+"ki=whois.nic.mu\n"
//			+"kp=whois.kcce.kp\n"
//			+"kr=whois.nic.or.kr\n"
//			+"kz=whois.nic.kz\n"
//			+"la=whois.nic.la\n"
//			+"li=whois.nic.li\n"
//			+"lt=whois.domreg.lt\n"
//			+"lu=whois.dns.lu\n"
//			+"lv=whois.nic.lv\n"
//			+"ly=whois.nic.ly\n"
//			+"ma=whois.iam.net.ma \n"
//			+"mc=whois.ripe.net\n"
			+"me=whois.meregistry.net\n"
//			+"mg=whois.nic.mg\n"
//			+"ms=whois.nic.ms\n"
//			+"mu=whois.nic.mu\n"
//			+"mx=whois.nic.mx\n"
//			+"my=whois.domainregistry.my\n"
//			+"na=whois.na-nic.com.na\n"
//			+"nc=whois.cctld.nc\n"
//			+"nf=whois.nic.nf\n"
//			+"ng=whois.register.net.ng\n"
//			+"nl=whois.domain-registry.nl\n"
//			+"no=whois.norid.no\n"
//			+"nu=whois.nic.nu\n"
//			+"nz=whois.srs.net.nz\n"
//			+"pe=whois.nic.pe\n"
//			+"co.pl=whois.co.pl\n"
//			+"pl=whois.dns.pl\n"
//			+"pm=whois.nic.fr\n"
//			+"pr=whois.nic.pr\n"
//			+"ps=whois.pnina.ps\n"
//			+"pt=whois.dns.pt\n"
//			+"re=whois.nic.fr\n"
//			+"ro=whois.rotld.ro\n"
//			+"edu.ru=whois.informika.ru\n"
//			+"ru=whois.ripn.net\n"
//			+"sa=whois.nic.net.sa\n"
//			+"sb=whois.coccaregistry.net\n"
//			+"se=whois.nic-se.se\n"
//			+"sg=whois.nic.net.sg\n"
//			+"sh=whois.nic.sh\n"
//			+"si=whois.arnes.si\n"
//			+"sk=whois.sk-nic.sk\n"
//			+"sl=whois.nic.sl\n"
//			+"sm=whois.ripe.net\n"
//			+"sn=whois.nic.sn\n"
//			+"st=whois.nic.st\n"
//			+"su=whois.ripn.net\n"
			+"tc=whois.adamsnames.tc\n"
			+"tf=whois.nic.tf\n"
			+"th=whois.thnic.co.th\n"
//			+"tk=whois.dot.tk\n"
			+"tl=whois.nic.tl\n"
//			+"tm=whois.nic.tm\n"
			+"to=whois.tonic.to\n"
//			+"tr=whois.nic.tr\n"
			+"tv=whois.nic.tv\n"
//			+"tw=whois.twnic.net.tw\n"
//			+"tz=whois.tznic.or.tz\n"
			+"ua=whois.net.ua\n"
			+"ug=www.registry.co.ug\n"
			+"ac.uk=whois.ja.net\n"
			+"gov.uk=whois.ja.net\n"
//			+"uk=whois.nic.uk\n"
//			+"fed.us=whois.nic.gov\n"
			+"us=whois.nic.us\n";
//			+"uy=whois.nic.org.uy\n"
//			+"uz=whois.cctld.uz\n"
//			+"va=whois.ripe.net\n"
//			+"ve=whois.nic.ve\n"
//			+"vg=whois.adamsnames.tc\n"
//			+"wf=whois.nic.fr\n"
//			+"ws=whois.samoanic.ws\n"
//			+"yt=whois.nic.fr\n"
//			+"ac.za=whois.ac.za\n"
//			+"co.za=whois.coza.net.za\n"
//			+"gov.za=whois.gov.za\n";

		
		
		Properties props = new Properties();
		try {
			props.load(new ByteArrayInputStream(tldServersStr.getBytes()));
		} catch (IOException e) {
			e.printStackTrace();
		}
				
		props.setProperty("com", "whois.crsnic.net");
		props.setProperty("net", "whois.crsnic.net");
		props.setProperty("org", "whois.publicinterestregistry.net");

		return props;
	}

	private static HashMap<String, WhoisResponseParser> createResponseParserMap() {
	
	//		WhoisResponseParser defaultWhoisResponseParser = new DefaultWhoisResponseParser();
	
			HashMap<String, WhoisResponseParser> table = new HashMap<String, WhoisResponseParser>();
	//		table.put("tv", defaultWhoisResponseParser);
	//		table.put("com", defaultWhoisResponseParser);
	//		table.put("org", defaultWhoisResponseParser);
	//		table.put("net", defaultWhoisResponseParser);
	//		table.put("edu", defaultWhoisResponseParser);
	//		table.put("cc", defaultWhoisResponseParser);
	//		table.put("in", defaultWhoisResponseParser);
	//		table.put("biz", defaultWhoisResponseParser);
	//		table.put("mobi", defaultWhoisResponseParser);
	//		table.put("de", defaultWhoisResponseParser);
	//		table.put("info", defaultWhoisResponseParser);
	//		table.put("me", defaultWhoisResponseParser);
	
			return table;
		}

	public static WhoisResponseParser getWhoisResponseParserForTld (String tld) {
		if (WHOIS_RESPONSE_PARSER_MAP.containsKey(tld)) {
			return WHOIS_RESPONSE_PARSER_MAP.get(tld);
		}
		else {
			return new DefaultWhoisResponseParser();
		}
	}
}
